import EventDefines from "../Constants/EventDefines";
import Oriented from "../Constants/Oriented";
import MainPlayer from "../Entity/MainPlayer";
import G from "../Utilities/Global";
import eState from "../Lib/StateMachine/eState";
import StateEvent from "../Lib/StateMachine/StateEvent";
import AnimationController from "./AnimationController";
import Constants from "../Constants/Constants";

/**
 * 移动控制类
 * created by Five on 2018年11月15日11:48:22
 */
const { ccclass, property } = cc._decorator;

@ccclass
export default class PlayerMoveController extends cc.Component {
    @property
    Speed: number = 0;

    // 父节点管理碰撞,子节点管理动画
    @property(cc.Node)
    SpineNode: cc.Node = null;

    private _position: cc.Vec2 = cc.Vec2.ZERO;
    private _rigidbody: cc.RigidBody = null;
    private _mainplayer: MainPlayer = null;
    private _oriented: Oriented = Oriented.RIGHT;

    private _anim: AnimationController = null;

    start() {
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.keyDown, this);
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.keyUp, this);
        this._rigidbody = this.getComponent(cc.RigidBody);
        this._mainplayer = this.getComponent(MainPlayer);
        this._anim = new AnimationController(this.SpineNode, "role");
        this._anim.initClips();
        this._mainplayer.setAnim(this._anim);
        this._mainplayer.setMove(this);

        this.schedule(this.stepSound, 0.3);

        G().CurScene.moveSpeedTest.string = "105";
        G().CurScene.jumpForceTest.string = "23500";
    }

    onDestroy() {
        cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.keyDown, this);
        cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.keyUp, this);
    }

    jumpDuration = 0;
    update(dt: number) {
        if (this._mainplayer.Dead)
            return;

        // 只允许配置为可位移的状态下产生位移
        if (this._mainplayer.Fsm.Current.Moveable) {
            let x = this.node.position.x + this._position.x * dt;
            let y = this.node.position.y + this._position.y * dt;
            let target = new cc.Vec2(x, y);
            let forward = G().Calc.FU(target, this._oriented);
            let entityTar = G().CurScene.MapData.GetWallByPosition(forward);
            if (!entityTar)
                this.node.position = new cc.Vec2(x, y);
        }
        // 没有速度的移动, 退出移动状态
        if (this._mainplayer.Fsm.CurrentState == eState.MOVE && this._position.mag() == 0)
            this._mainplayer.Fsm.Quit();

        // if (this._rigidbody.linearVelocity.y != 0) {
        //     this.jumpDuration += dt;
        //     cc.log('SPEED = ' + this._rigidbody.linearVelocity +
        //         " jumpDuration = " + this.jumpDuration +
        //         " position = " + this.node.position);
        // }
        this.Speed = +G().CurScene.moveSpeedTest.string;
    }

    // 用于切换步伐
    private step: boolean = false;
    stepSound() {
        if (this._mainplayer.Fsm.CurrentState == eState.MOVE) {
            G().Sound.playSFX(this.step ? "role_walk1" : "role_walk2");
            this.step = !this.step;
        }
    }

    keyDown(event: cc.Event.EventKeyboard) {
        let state: StateEvent;
        switch (event.keyCode) {
            // @ts-ignore
            case cc.macro.KEY.d:
                this.move(false);
                break;
            // @ts-ignore
            case cc.macro.KEY.a:
                this.move(true);
                break;
            // @ts-ignore
            case cc.macro.KEY.space:
                this.jump();
                break;
            // @ts-ignore
            case cc.macro.KEY.z:
                state = new StateEvent(null, () => {
                    this._mainplayer.Fsm.Quit();
                    this._mainplayer.shot(this._oriented)
                });
                this._mainplayer.Fsm.ChangeState(eState.ATTACK, state);
                break;
            // @ts-ignore
            case cc.macro.KEY.j:
                this.makeOrdestory();
                break;
            // @ts-ignore
            case cc.macro.KEY.s:
                this.sqautMake();
                break;
            // @ts-ignore
            case cc.macro.KEY.k:
                G().CurScene.mController.KillAll();
                break;
            // @ts-ignore
            case cc.macro.KEY.p:
                G().CurScene.mController.TimeFreeze(5);
                break;
            // @ts-ignore
            case cc.macro.KEY.o:
                // G().CurScene.GameEnd(true);
                break;
        }
    }

    keyUp(event: cc.Event.EventKeyboard) {
        let state: StateEvent;
        switch (event.keyCode) {
            // @ts-ignore
            case cc.macro.KEY.d:
                if (this._mainplayer.Fsm.CurrentState == eState.MOVE)
                    this._mainplayer.Fsm.Quit();
                this._position = cc.Vec2.ZERO;
                break;
            // @ts-ignore
            case cc.macro.KEY.a:
                if (this._mainplayer.Fsm.CurrentState == eState.MOVE)
                    this._mainplayer.Fsm.Quit();
                this._position = cc.Vec2.ZERO;
                break;
            // @ts-ignore
            case cc.macro.KEY.s:
                this._mainplayer.Fsm.Quit();
                break;
        }
    }

    turn() {
        this.SpineNode.is3DNode = true;
        this.SpineNode.eulerAngles = this._oriented != Oriented.RIGHT ? Constants.OppsiteRotate : cc.Vec3.ZERO;

        
        // this.SpineNode.rotationY = this._oriented == Oriented.RIGHT ? 180 : 0;
    }

    jump() {
        let state: StateEvent;
        if (this._rigidbody.linearVelocity.y != 0)
            return;
        // 打断前一个动作
        if (!this._mainplayer.Fsm.Current.Moveable) {
            state = new StateEvent(null, () => {
                // 下坠状态
                if (this._rigidbody.linearVelocity.mag() == 0) {
                    this._mainplayer.Fsm.Quit();
                } else {
                    this._mainplayer.Fsm.Quit();
                    // cc.log('droping');
                }
            });
        } else {
            state = new StateEvent(null, () => {
                this._mainplayer.Fsm.Back();
            });
        }
        this.jumpDuration = 0;
        // m = h * w / 1024;
        // g = 0,-320;
        // Ft = m √2gh;
        // t = 1 / fps;
        // duration = F/m*t/g + √2h/g
        let forceY = G().CurScene.jumpForceTest.string;
        this._rigidbody.applyForceToCenter(cc.v2(0, +forceY), true);
        this._mainplayer.Fsm.ChangeState(eState.JUMP, state);
    }

    makeOrdestory() {
        let state: StateEvent;
        state = new StateEvent(null, () => {
            this._mainplayer.Fsm.Quit();
            this._mainplayer.makeOrdestroy(this._oriented, false);
        });
        this._mainplayer.Fsm.ChangeState(eState.ATTACK, state);
    }

    sqautMake() {
        let state: StateEvent;
        state = new StateEvent(null, () => {
            this._mainplayer.Fsm.Quit();
            this._mainplayer.makeOrdestroy(this._oriented, true);
        });
        if (this._mainplayer.Fsm.CurrentState != eState.ATTACK) {
            this._mainplayer.Fsm.ChangeState(eState.SQAUT, state);
        }
    }

    stop() {
        if (this._mainplayer.Fsm.CurrentState == eState.MOVE)
            this._mainplayer.Fsm.Quit();
        this._position = cc.Vec2.ZERO;
    }

    move(left: boolean) {
        let state: StateEvent;

        if (left) {
            // 左
            this._oriented = Oriented.LEFT;
            this._position.x = -this.Speed;
            if (this._mainplayer.Fsm.CurrentState == eState.IDLE) {
                this._mainplayer.Fsm.ChangeState(eState.MOVE, state);
            }
        } else {
            // 右
            this._oriented = Oriented.RIGHT;
            this._position.x = this.Speed;
            if (this._mainplayer.Fsm.CurrentState == eState.IDLE) {
                this._mainplayer.Fsm.ChangeState(eState.MOVE, state);
            }
        }
        this.turn();
    }
}